------------------------------------- Chapitre VIII - Cryptographie -------------------------------------
RSA - exemple de chiffrement asymétrique simple.
Outils nécessaires :
OllyDbg (by Oleh Yuschuk)
PEiD et son plugin kanal (by Jibz, Qwerton & snaker) ou tout autre analyseur d'exécutables !
rsab0x (by Team RED)
RSA-Tool 2 (by tE!)
- Les notions de base des précédents cours sur l’assembleur et l’utilisation d’Ollydbg sont considérées acquises.
Cible :
Plato DVD Ripper v12.12.01
Editeur : Plato Software Inc
Je dis simple bien que j’ai mis un certain temps à le comprendre ,
mais sur les différentes cibles que j’ai approchées, celle-ci fait partie des cas simples. Donc merci uLysse de me l’avoir
indiqué depuis quelque temps, je l’ai ressortie du placard
.
Tout d'abord, vous pouvez, ou plutôt vous DEVEZ aller lire cet article, qui explique le fonctionnement global du RSA : https://en.wikipedia.org/wiki/RSA_%28algorithm%29 ou en version française : http://fr.wikipedia.org/wiki/Rivest_Shamir_Adleman
Notre cible n’est plus toute jeune et a dû être déjà keygennée
.
Pour les outils, je vous conseillerais d’utiliser rsab0x de la team RED au lieu de Keygenner assistant, parce que j’ai rencontré quelques bogues avec ce dernier (ça reste un outil très pratique, même s’il est un peu bogué), par exemple :
Bref, on commence par scanner un petit coup avec PEiD et le plugin Kanal. On voit l’utilisation de Miracl, une librairie de BigNum. On n’est pas certain qu’elle soit là pour du RSA, mais c’est déjà une indication pour une éventuelle utilisation.
Chargeons la cible dans le debogueur, lancez la et rentrez les infos d’enregistrement :
Ce qui nous donne :
Une petite recherche de strings, on ne trouve qu’une seule occurrence de « Invalid license name… » :
On va naturellement aller regarder ce qui se passe dans le CALL 004162D0
. On remarque tout de suite qu’on sort rapidement de la
routine si EAX ne vaut pas 30h (48d) :
004162FF |. 83F8 30 CMP EAX,30
00416302 |. 74 19 JE SHORT dvdrippe.0041631D
Pour la prochaine fois, rentrons directement un serial de 30h caractères
, et posons un petit BP en 004162FF. Il s’agit de la comparaison de la longueur du serial avec 30h,
continuons à tracer :
On remarque ici que le serial est coupé en 3 parties distinctes de 16d (10h) caractères. Puis
on tombe, sur 3 strings qui pourraient être des bignums . La
même fonction est appelée chaque fois après qu’ils soient poussés en argument. Notez au passage que la valeur d’EAX en sortie
du CALL dvdrippe.00416170 sera déterminante pour la validation du serial. EAX est stocké à l’issue de chaque fonction :
Ici : 004163D2 |. 8BF0 MOV ESI,EAX
pour le premier.
En : 004163D9 |. 8BF8 MOV EDI,EAX
pour le second.
et le dernier restera dans EAX.
Ci-dessous, on comprend que la valeur d’eax devra être égale à la somme de EDI + ESI, soit la somme des valeurs d’EAX en sortie des 2 premiers CALL 00416170.
0041640A |. 03FE ADD EDI,ESI
0041640C |. 33C9 XOR ECX,ECX
0041640E |. 3BF8 CMP EDI,EAX
00416410 |. 0F94C1 SETE CL
00416413 |. 5F POP EDI
00416414 |. 5E POP ESI
00416415 |. 5B POP EBX
00416416 |. 8BC1 MOV EAX,ECX
Allons faire un tour dans le CALL 00416170, et descendez quelque peu dans le code. Cette ligne doit vous sauter aux yeux :
0041624C |. 68 B8A14700 PUSH dvdrippe.0047A1B8 ; ASCII "10001"
Cette valeur, 10001h ou 65537d est typique du RSA et est couramment utilisée comme clé publique E.
Nous pouvons maintenant penser que nous avons trois N dont les deux premiers sont identiques, que la clé publique sera commune, et comme chacune de nos parties de serial découpé sont respectivement poussées dans l’ordre, en argument avant chaque call, on peut imaginer que chaque partie sera le texte à chiffrer (M) selon la formule suivante : C = M^E(mod N).
Nous aurons 3 chiffrements RSA successifs. Faisons un essai pour s’en assurer.
On pose :
Nous allons donc déchiffrer trois valeurs pour tester cette hypothèse, et il sera plus facile de suivre nos valeurs une fois chiffrées
.
Pour cela il nous faut calculer la clef privée D de chaque modulo découvert (le couple N/E formant
la clef publique). Lancez Rsa-Tool 2, puis cliquez sur "Exact size"(1) si vous voulez connaître la taille
de la clef.
Ensuite il vous faudra retrouver les nombres premiers P et Q en cliquant sur "Factor N"(2) puis il ne reste
plus qu’à calculer D (3) .
Dans notre cas, avec du 64 bits, c’est très rapide. Mais cela peut s’avérer extrêmement long avec des clefs de grandes tailles.
N’oubliez pas de vérifier que vous êtes bien en base16.
Notez la clef privée : (celle des 2 premiers modulos) :
Puis recommencez avec le 3ème modulo qui sera utilisé pour la 3ème partie du serial :
Je vais déchiffrer les 3 valeurs suivantes, selon la formule M = C^D (Mod N) pour composer mon fake serial (utiliser rsab0x pour
éviter les surprises ). Si le M obtenu ne fait pas 16d
caractères, ajoutez un 0 devant. Pour obtenir des valeurs déchiffrées correspondantes en ASCII, il nous faut encoder leurs
valeurs en hexa :
11111 =hexEnc=> 3131313131 =RSADechif=> 3559D94398FD3C3F
22222 =hexEnc=> 3232323232 =RSADechif=> 36916D678A42F0D2
33333 =hexEnc=> 3333333333 =RSADechif=> 4614C5D25C379B5A
=> 3559D94398FD3C3F36916D678A42F0D24614C5D25C379B5A
On retourne essayer ce serial, il fait bien 30h, donc on continue… le serial est découpé puis la première partie est poussée avec le premier modulo N, donc rentrons dans ce CALL, et traçons jusqu’ici :
00416210 |> 0FBE1437 /MOVSX EDX,BYTE PTR DS:[EDI+ESI]
00416214 |. |52 |PUSH EDX
00416215 |. |E8 7F070400 |CALL <dvdrippe.IsHexNumber> ; verifie si chaque caractere de la chaine
est sur la plage HEX (0-9)(A-F)
0041621A |. |83C4 04 |ADD ESP,4
0041621D |. |85C0 |TEST EAX,EAX
0041621F |. |0F84 80000000 |JE dvdrippe.004162A5 ; sinon, on degage,
pas d'encryption :(
00416225 |. |83C6 01 |ADD ESI,1
00416228 |. |3B7424 10 |CMP ESI,DWORD PTR SS:[ESP+10]
0041622C |.^\7C E2 \JL SHORT dvdrippe.00416210
Cette boucle vérifie que la chaîne à chiffrer ne contient que des caractères hexadécimaux, c’est assez logique…, sinon on saute.
On continue de tracer, et on arrive là :
En suivant EBX dans le dump, on retrouve notre chaîne à chiffrer :
Puis on retrouve la chaîne déchiffrée en suivant ESI après la fonction :
Dans le dump on lit 3559D94398FD3C3F sous la forme inversée 3F 3C FD 98 43 D9 59 35, idem pour 3131313131
, mais là ça ne se voit pas .
On continue de tracer pour tenter de voir ce qui détermine EAX, jusqu’au PUSH EDX, on suit EDX dans le dump, et on tombe sur notre chaîne déchiffrée :
Tracez en step over par-dessus la fonction, regardez EAX à la sortie, on a EAX = 2B67h
. Soit la conversion en hexa de 11111d. On sort
de la routine et on remarque en 004163D2, que 2B67h est stocké dans ESI.
Continuez ainsi avec les 2 autres chaines. On aura 56CEh pour la 2ème chaîne qui sera placée dans EDI , puis 8235h sera dans EAX pour la 3ème chaîne, en arrivant ici :
0041640A |. 03FE ADD EDI,ESI
0041640C |. 33C9 XOR ECX,ECX
0041640E |. 3BF8 CMP EDI,EAX
00416410 |. 0F94C1 SETE CL
00416413 |. 5F POP EDI
00416414 |. 5E POP ESI
00416415 |. 5B POP EBX
00416416 |. 8BC1 MOV EAX,ECX
Vous remarquez tout de suite qu’on ajoute ESI à EDI avant de comparer cette somme avec EAX. Il faut donc que la valeur ASCII de la 3ème chaîne chiffrée avec le 2ème modulo, soit égale à la somme des valeurs ASCII des deux autres chaînes chiffrées avec le 1er modulo, pour que le serial soit valide.
Dans notre cas, pas besoin de faire le test…11111d+22222d=33333d
, donc le serial doit être valide
, et ce n’est même pas volontaire
. Notez qu’en cas d’échec de la conversion décimale
en hex, la valeur d’EAX sera à zéro, et la condition ne sera pas vérifiée…c’est ce qui m’a
un peu gêné au début, car je déchiffrais 11111 au lieu de 3131313131h, donc la valeur ASCII
n’était pas convertissable en hex, puisque non décimale
... On ne prendra donc que des chiffres pour la génération aléatoire de valeurs lors de la création du keygen.
Je dois quand même vous parler des méthodes pour repérer l’utilisation de librairie de crypto. Même si dans ce cas, PEiD repère la librairie Miracl, ce n’est pas toujours le cas… J’aime bien charger la cible dans IDA, appliquer les différentes signatures habituellement utilisées comme FGInt, BigLib ou le pack de signatures de dihux.
Vous pouvez ensuite produire un fichier .map que vous pourrez importer aisément dans Olly, à l’aide du plugin GODUP. Ce dernier permet même d’importer directement des signatures IDA.
Mais là n’est pas le sujet du tuto .
Un petit merci particulier à uLysse_31 pour sa patience et son aide.
La source du keygen est inclue dans le pack, j’ai simplement modifié un template récupéré sur l’excellent BLOG de xylitol.
Pour compiler la source, il vous faut Masm et WinASM.